/************************************************************************
* render.c
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "common.h"
#include "graphics.h"
#include "ui.h"

#include <math.h>

static struct {
	int ticks;
	int tticks;
	int fticks;
	int font_init;
	float dtime;
	matrix_t projection;
} render_data = {
	0,
	0,
	0,
	0,
	0.1
};

/* get client-side frame time */
float client_dtime()
{
	return render_data.dtime;
}

/* get the current projection matrix */
matrix_t *render_get_projection_matrix()
{
	return &render_data.projection;
}

void render_set_projection_matrix(matrix_t *m)
{
	float fov;
	float near_plane;
	float far_plane;
	float ratio;
	float x;
	float y;
	float z;

	if (m) {
		render_data.projection = *m;
		return;
	}

	fov = 70.0;
	near_plane = 0.1;
	far_plane = 1000.0;

	fov = math_degrees_to_radians(fov/2.0);

	ratio = (float)wm_data.size.width/(float)wm_data.size.height;
	y = (1.0/tan(fov));
	x = y/ratio;
	z = far_plane-near_plane;

	matrix_init(&render_data.projection);

	render_data.projection.data[0] = x;
	render_data.projection.data[5] = y;
	render_data.projection.data[10] = -((far_plane+near_plane)/z);
	render_data.projection.data[11] = -1;
	render_data.projection.data[14] = -((2.0*near_plane*far_plane)/z);
	render_data.projection.data[15] = 0;
}

/* clear the frame */
void render_pre()
{
	if (!render_data.ticks)
		render_data.ticks = time_ticks();
	events_main();
}

/* render to frame */
void render_post()
{
	camera_t *cam;
	ui_render();

	if (wm_data.cursor.mat) {
		int mouse[2];
		events_get_mouse(mouse);
		render2d_quad_mat(wm_data.cursor.mat,mouse[0]+wm_data.cursor.x,mouse[1]+wm_data.cursor.y,wm_data.cursor.w,wm_data.cursor.h);
	}

	cam = camera_get();

	/* should get this from sky when in-game */
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
/*
	water_prerender(cam);
*/
	render_map(cam,NULL);
/*
	water_render();
*/
	render3d(cam,NULL);

	particles_render();

	glDisable(GL_DEPTH_TEST);

	render2d();

	wm_update();

	/* calculate a scale factor for smooth animations */
	render_data.tticks = interval_delay(render_data.ticks,wm_data.frame_cap);
	wm_data.lfps_i++;
	if (wm_data.lfps_i > 3)
		wm_data.lfps_i = 0;
	wm_data.lfps[wm_data.lfps_i] = calc_fps(render_data.ticks,render_data.tticks);
	wm_data.fps = (wm_data.lfps[0]+wm_data.lfps[1]+wm_data.lfps[2]+wm_data.lfps[3])/4;
	render_data.dtime = time_dtime(render_data.ticks);
	render_data.ticks = render_data.tticks;
}
